/* 
 * Copyright 2013 Sébastien Mouquet.
 * 
 * This file is part of ECovoiturage.
 * 
 * ECovoiturage is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ECovoiturage is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ECovoiturage. If not, see http://www.gnu.org/licenses/.
 */
package com.smouquet.ecovoiturage.ui.page.root.moncompte;

import com.smouquet.ecovoiturage.core.domain.Entreprise;
import com.smouquet.ecovoiturage.core.domain.Utilisateur;
import com.smouquet.ecovoiturage.ui.NotificationUtil;
import com.vaadin.data.Validator;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.fieldgroup.PropertyId;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.Runo;
import com.vaadin.util.ReflectTools;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;

/**
 * Formulaire de modification d'un compte utilisateur.
 * 
 * @author sebastien.mouquet
 */
public class MonCompteForm extends GridLayout
                           implements Button.ClickListener
{
    private static final int NB_COL = 2;
    private static final int NB_ROW = 6;
    
    private FormLayout layout;
    
    @PropertyId("nom")
    private TextField tfNom;
    @PropertyId("email")
    private TextField tfEmail;
    private TextField tfEmailConfirm;
    @PropertyId("mdp")
    private PasswordField pfMdp;
    private PasswordField pfMdpConfirm;
    @PropertyId("adresse")
    private TextField tfAdresse;
    @PropertyId("entreprise")
    private ComboBox cbEntreprise;
    
    private Button btnSauvegarder;
    
    private FieldGroup fgForm;
    
    private List<Entreprise> entreprises;
    private Utilisateur utilisateur;
    
    
    public MonCompteForm(Utilisateur utilisateur)
    {
        super(NB_COL, NB_ROW);
        this.utilisateur = utilisateur;
        layout();
    }
    
    public MonCompteForm(Utilisateur utilisateur, List<Entreprise> entreprises)
    {
        super(NB_COL, NB_ROW);
        this.utilisateur = utilisateur;
        this.entreprises = entreprises;
        layout();
    }

    
    public void setEntreprises(List<Entreprise> entreprises)
    {
        this.entreprises = entreprises;
        
        if(cbEntreprise != null) {
            prepareAndInstallCbEntrepriseContainer();
        }
    }

    /**
     * @return L'utilisateur modifié via le formulaire.
     */
    public Utilisateur getUtilisateur() {
        return utilisateur;
    }
    
    
    private void layout()
    {
        layout = new FormLayout();
        layout.setImmediate(true);
        
        tfNom = new TextField("Nom (utilisé pour l'affichage)");
        tfNom.setWidth(100, Unit.PERCENTAGE);
        tfNom.setImmediate(true);
        tfNom.setRequired(true);
        tfNom.setMaxLength(80);
        tfNom.setValidationVisible(true);
        tfNom.setNullRepresentation("");
        
        tfEmail = new TextField("Email");
        tfEmail.setWidth(100, Unit.PERCENTAGE);
        tfEmail.setImmediate(true);
        tfEmail.setRequired(true);
        tfEmail.setMaxLength(100);
        tfEmail.setValidationVisible(true);
        tfEmail.setNullRepresentation("");
        
        tfEmailConfirm = new TextField("Confirmation de l'email");
        tfEmailConfirm.setWidth(100, Unit.PERCENTAGE);
        tfEmailConfirm.setImmediate(true);
        tfEmailConfirm.setRequired(true);
        tfEmailConfirm.setMaxLength(100);
        tfEmailConfirm.setValidationVisible(true);
        tfEmailConfirm.setNullRepresentation("");
     
        pfMdp = new PasswordField("Mot de passe");
        pfMdp.setWidth(100, Unit.PERCENTAGE);
        pfMdp.setImmediate(true);
        pfMdp.setRequired(true);
        pfMdp.setMaxLength(15);
        pfMdp.setValidationVisible(true);
        pfMdp.setNullRepresentation("");
        
        pfMdpConfirm = new PasswordField("Confirmation du mot de passe");
        pfMdpConfirm.setWidth(100, Unit.PERCENTAGE);
        pfMdpConfirm.setImmediate(true);
        pfMdpConfirm.setRequired(true);
        pfMdpConfirm.setMaxLength(15);
        pfMdpConfirm.setValidationVisible(true);
        pfMdpConfirm.setNullRepresentation("");
        
        tfAdresse = new TextField("Adresse");
        tfAdresse.setWidth(100, Unit.PERCENTAGE);
        tfAdresse.setImmediate(true);
        tfAdresse.setMaxLength(250);
        tfAdresse.setNullRepresentation("");
        
        cbEntreprise = new ComboBox("Entreprise");
        cbEntreprise.setWidth(100, Unit.PERCENTAGE);
        cbEntreprise.setImmediate(true);
        cbEntreprise.setRequired(true);
        prepareAndInstallCbEntrepriseContainer();
        
        btnSauvegarder = new Button("Sauvegarder");
        btnSauvegarder.addStyleName(Runo.BUTTON_SMALL);
        btnSauvegarder.addStyleName(Runo.BUTTON_DEFAULT);
        btnSauvegarder.addClickListener(this);
        
        addComponent(tfNom, 0, 0, 1, 0);
        addComponent(tfEmail, 0, 1, 0, 1);
        addComponent(tfEmailConfirm, 1, 1, 1, 1);
        addComponent(pfMdp, 0, 2, 0, 2);
        addComponent(pfMdpConfirm, 1, 2, 1, 2);
        addComponent(tfAdresse, 0, 3, 1, 3);
        addComponent(cbEntreprise, 0, 4, 1, 4);
        addComponent(btnSauvegarder, 0, 5, 1, 5);
        
        setComponentAlignment(btnSauvegarder, Alignment.BOTTOM_CENTER);
        
        addComponent(layout);
        
        fgForm = new FieldGroup(new BeanItem<Utilisateur>(utilisateur));
        fgForm.bindMemberFields(this);
        tfEmailConfirm.setValue(utilisateur.getEmail());
        pfMdpConfirm.setValue(utilisateur.getMdp());
        
        setWidth(100, Unit.PERCENTAGE);
        setSpacing(true);
    }
    
    private void prepareAndInstallCbEntrepriseContainer()
    {
        BeanItemContainer<Entreprise> container = new BeanItemContainer<Entreprise>(Entreprise.class);

        for(Entreprise e : entreprises) {
            container.addBean(e);
        }
        
        cbEntreprise.setContainerDataSource(container);
        cbEntreprise.setItemCaptionMode(AbstractSelect.ItemCaptionMode.PROPERTY);
        cbEntreprise.setItemCaptionPropertyId("nom");
    }
    

    @Override
    public void buttonClick(ClickEvent event)
    {
        try
        {
            if( pfMdp.getValue() == null || pfMdpConfirm.getValue() == null ||
                !pfMdp.getValue().equals(pfMdpConfirm.getValue()) )
            {
                NotificationUtil.showWarningNotification("Mot de passe absent ou non concordant");
            }
            else if( tfEmail.getValue() == null || tfEmailConfirm.getValue() == null ||
                     !tfEmail.getValue().equals(tfEmailConfirm.getValue()) )
            {
                NotificationUtil.showWarningNotification("Email absent ou non concordant");
            }
            else
            {
                fgForm.commit();
                fireEvent(new SaveAccountEvent(this, utilisateur));
            }
            
        } catch(Validator.InvalidValueException ex) {
            NotificationUtil.showWarningNotification("Formulaire incomplet et/ou données invalides");
        } catch(FieldGroup.CommitException ex) {
            NotificationUtil.showWarningNotification("Formulaire incomplet et/ou données invalides");
        }
    }
    
    
    public static class SaveAccountEvent extends Event
    {
        private Utilisateur utilisateur;
        
        public SaveAccountEvent(Component source, Utilisateur utilisateur) {
            super(source);
            this.utilisateur = utilisateur;
        }

        public Utilisateur getUtilisateur() {
            return utilisateur;
        }
    }
    
    public interface SaveAccountListener extends Serializable
    {
        public static final Method METHOD = ReflectTools.findMethod(SaveAccountListener.class, "onSaveAccount", SaveAccountEvent.class);
        
        void onSaveAccount(SaveAccountEvent event);
    }
    
    public void addSaveAccountListener(SaveAccountListener listener)
    {
        addListener(SaveAccountEvent.class, listener, SaveAccountListener.METHOD);
    }
    
    public void removeSaveAccountListener(SaveAccountListener listener)
    {
        addListener(SaveAccountEvent.class, listener, SaveAccountListener.METHOD);
    }
}
